#pragma once
#include"requestor.hpp"

// 获取异步结果
class RpcCallFuture
{
public:
    RpcCallFuture() {}

    // 移动构造
    RpcCallFuture(std::future<BaseMessage::ptr> fu, Requestor::ptr requestor) 
        : _future(std::move(fu)), _requestor(requestor) {}

    // 获取结果
    const Json::Value get()
    {
        RpcResponse::ptr response = std::dynamic_pointer_cast<RpcResponse>(_future.get());
        RCode code = response->getRcode();
        std::string id = response->getId();
        if (code != RCode::OK)
        {
            LOG_ERROR << errStr[code];
            _requestor->remove(id);
            return Json::Value();
        }

        _requestor->remove(id);
        return response->getResult();
    }

    bool empty()
    {
        return _requestor == nullptr;
    }

    // 移动构造
    RpcCallFuture(RpcCallFuture&) = delete;
    RpcCallFuture(RpcCallFuture&& rpc_call_fu)
    {
        _future = std::move(rpc_call_fu._future);
        _requestor = rpc_call_fu._requestor;
    }
private:
    std::future<BaseMessage::ptr> _future;
    Requestor::ptr _requestor = nullptr; // 请求管理的删除 
};

//这个模块提供用户层的直接rpc调用接口
class RpcCaller
{
public:
    using ptr = std::shared_ptr<RpcCaller>;
    using callback = std::function<void(const Json::Value result)>;

    RpcCaller(Requestor::ptr comm) 
        :_requestor(comm) {}

    // 同步
    bool callSync(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& parameters, Json::Value& result, BaseProtocol::ptr protocol) {
        auto req = createRpcRequest(method, parameters);
        BaseMessage::ptr res = MessageFactory::create<RpcResponse>();
        auto ret = _requestor->sendSync(conn, req, protocol);
        if (ret.first)
        {
            RpcResponse::ptr response = std::dynamic_pointer_cast<RpcResponse>(ret.second);
            RCode rcode = response->getRcode();
            if (rcode != RCode::OK)
            {
                LOG_WARN << errStr[rcode];
                return false;
            }

            result = response->getResult();
        }
        _requestor->remove(req->getId());
        return ret.first;
    }

    // 异步
    RpcCallFuture callAsync(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& parameters, BaseProtocol::ptr protocol)
    {
        auto req = createRpcRequest(method, parameters);
        auto ret = _requestor->sendAsync(conn, req, protocol);
        if (ret.first)
        {
            return RpcCallFuture(std::move(ret.second), _requestor);
        }
        return RpcCallFuture();
    }


    // 回调
    bool callBack(const BaseConnection::ptr& conn, const std::string& method, const Json::Value& parameters, callback cb, BaseProtocol::ptr protocol)
    {
        auto req = createRpcRequest(method, parameters);
        return _requestor->sendCallBack(conn, req, protocol, std::bind(&RpcCaller::help, this, cb, std::placeholders::_1));
    }

private:
    void help(callback cb, BaseMessage::ptr msg)
    {
        // 取出结果
        RpcResponse::ptr res = std::dynamic_pointer_cast<RpcResponse>(msg);
        RCode code = res->getRcode();
        if (code != RCode::OK)
        {
            LOG_ERROR << errStr[code];
        }
        else
        {
            cb(res->getResult());
        }
        _requestor->remove(res->getId());
    }

private:
    BaseMessage::ptr createRpcRequest(const std::string& method, const Json::Value& parameters)
    {
        auto req = MessageFactory::create<RPCRequest>();
        req->setType(MSG_Type::RPC_REQ);
        req->setId();
        req->setMethod(method);
        req->setParameters(parameters);
        return req;
    }
    
private:
    Requestor::ptr _requestor;
};